package com.aduerr.v1shouyin.view;

import android.content.Context;
import android.graphics.Paint;
import androidx.appcompat.widget.AppCompatTextView;
import android.util.AttributeSet;


/**
 * 自动调整TextView字体大小以顺应文字长度控件
 */
public class AutoAjustSizeTextView extends AppCompatTextView {
    private static float DEFAULT_MIN_TEXT_SIZE = 18;
    private static float DEFAULT_MAX_TEXT_SIZE = 53;

    // Attributes
    private Paint testPaint;
    private float minTextSize, maxTextSize;

    private boolean isAutoComputerSize = true;

    public AutoAjustSizeTextView(Context context, AttributeSet attrs) {
        super(context, attrs);

        initialise();
    }

    private void initialise() {
        if(!isAutoComputerSize) return;
        testPaint = getPaint();

        if(maxTextSize <= DEFAULT_MIN_TEXT_SIZE) {
            maxTextSize = DEFAULT_MAX_TEXT_SIZE;
        }

        minTextSize = DEFAULT_MIN_TEXT_SIZE;
    }

    ;

    /**
     * Re size the font so the specified text fits in the text box * assuming
     * the text box is the specified width.
     */
    private void refitText(String text, int textWidth) {
        if(textWidth > 0) {
            int availableWidth = textWidth - this.getPaddingLeft()
                    - this.getPaddingRight();
            float trySize;
            if(getPxBySp(maxTextSize) < getTextSize()) {
                maxTextSize = getSpByPx(this.getTextSize());
                trySize = getPxBySp(maxTextSize);
            } else {
                trySize = this.getTextSize();
            }

            testPaint.setTextSize(trySize);
            boolean hasChange = false;
            int height = getHeight() - getPaddingBottom() - getPaddingTop();
            int line = getLineCount();
            int lineHeight = getLineHeight();
            if(autoSplitText() && trySize > minTextSize) {
                while((getSpByPx(trySize) > minTextSize)
                ) {
                    hasChange = true;

                    if(!autoSplitText()) {
                        trySize -= 2;
                        break;
                    } else {
                        trySize -= 1;
                    }
                    testPaint.setTextSize(trySize);
                }
            } else {
                if(line == 1 && line * lineHeight <= height && !autoSplitText()) {
                    while((getSpByPx(trySize) < maxTextSize)
                            && (testPaint.measureText(text) < availableWidth) && !autoSplitText()) {
                        hasChange = true;
                        trySize += 1;
                        testPaint.setTextSize(trySize);
                    }
                }
            }

            if(hasChange)
                this.setTextSize((int) getSpByPx(trySize));
        }

    }

    private float getSpByPx(float value) {
        return value / getResources().getDisplayMetrics().scaledDensity;
    }

    private float getPxBySp(float value) {
        return value * getResources().getDisplayMetrics().scaledDensity;
    }

    @Override
    protected void onTextChanged(CharSequence text, int start, int before,
                                 int after) {
        super.onTextChanged(text, start, before, after);
        if(!isAutoComputerSize) return;
        if(before == after) return;
        refitText(text.toString(), this.getWidth());
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        if(!isAutoComputerSize) return;
        if(w != oldw) {
            refitText(this.getText().toString(), w);
        }
    }

    public boolean isAutoComputerSize() {
        return isAutoComputerSize;
    }

    public void setAutoComputerSize(boolean autoComputerSize) {
        isAutoComputerSize = autoComputerSize;
    }

    private boolean autoSplitText() {
        String rawText = getText().toString();
        if(rawText.length() == 1)
            return false;
        final Paint tvPaint = testPaint; //paint，包含字体等信息
        final float tvWidth = getWidth() - getPaddingLeft() - getPaddingRight() - 10;
        //控件可用宽度

        //将原始文本按行拆分
        String[] rawTextLines = rawText.replaceAll("\r", "").split("\n");
        for(String rawTextLine : rawTextLines) {
            if(tvPaint.measureText(rawTextLine) < tvWidth) {
                //如果整行宽度在控件可用宽度之内，就不处理了
                return false;
            } else {
                //如果整行宽度超过控件可用宽度，则按字符测量，在超过可用宽度的前一个字符处手动换行
                float lineWidth = 0;
                for(int cnt = 0; cnt != rawTextLine.length(); ++cnt) {
                    char ch = rawTextLine.charAt(cnt);
                    lineWidth += tvPaint.measureText(String.valueOf(ch));
                    if(lineWidth < tvWidth) {
                    } else {
                        return true;
                    }
                }
                return true;
            }
        }

        return false;
    }
}
